home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
CH_6.1
/
XVOR
/
XVOR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
10KB
|
408 lines
/*
* xvor.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* XVOR
*
* compute Voronoi diagram or Delaunay triangulation
* for a set of points in the plane
*
* on unsorted data uniformly distributed in the unit square, routine
* voronoi uses about 20n+140\(srn bytes of storage; on sorted data,
* routine voronoi uses about 160\(srn
*
*
* input:
* each input line should consist of two real numbers, separated by
* white space.
* sorted input (option -s):
* the input is sorted by y coordinate (the second number in the pair);
* the first input line should be npoints xmin xmax ymin ymax; this
* describes the number of points and the range of the points; the
* information is used to determine internal hash table size; it need
* not be exact but performance suffers if it is grossly wrong.
*
* VORONOI output:
* there are four output record types.
* -->s a b indicates that an input point at coordinates a b was seen;
* -->l a b c indicates a line with equation ax + by = c.
* -->v a b indicates a vertex at a b.
* -->e l v1 v2 s1 s2 indicates a Voronoi segment which is a subsegment of
* line number l with endpoints numbered v1 and v2; if v1 or v2
* is -1, the line extends to infinity; e bisects the line segment
* delimited by sites s1 and s2
*
* DELAUNAY output:
* output: each output line is a triple i j k, giving the indices of
* the three points in a Delaunay triangle; points are
* numbered starting at 0.
*
*/
#include "xvor.h"
/* globals */
extern char *optarg;
extern int optind, opterr;
int VOR = ON; /* default: evaluate Voronoi diagram */
int TRIANGULATE = OFF;
int PRE_SORTED = ON; /* default: assume y-sorted data in input file */
int DBG = OFF;
int WRITE_FLAG = OFF;
FILE *fpIn, *fpOut;
/*
* scomp()
* DESCRIPTION:
* sort sites on y, then x, coord
* used with qsort!!
* ARGUMENTS:
* S1: first sort poiint (Point *)
* S2: second sort poiint (Point *)
* RETURN VALUE:
* 1, 0, -1 depending on x,y position
*/
int
scomp (S1, S2)
const void *S1, *S2;
{
const struct Point *s1 = S1;
const struct Point *s2 = S2;
if (s1->y < s2->y)
return (-1);
if (s1->y > s2->y)
return (1);
if (s1->x < s2->x)
return (-1);
if (s1->x > s2->x)
return (1);
return (0);
}
/*
* nextone()
* DESCRIPTION:
* return a single in-storage site
* ARGUMENTS:
* none
* RETURN VALUE:
* next site (struct Site *)
*/
struct Site *
nextone ()
{
struct Site *s;
if (siteidx < nsites) {
s = &sites[siteidx];
siteidx += 1;
return (s);
}
else
return ((struct Site *) NULL);
}
/*
* freadsites()
* DESCRIPTION:
* read all sites, sort, and compute xmin, xmax, ymin, ymax
* ARGUMENTS:
* file: pointer to open FILE
* RETURN VALUE:
* none
*/
void
freadsites (file)
FILE *file;
{
int i;
/*
* skip top line in .vin data file
*/
fscanf (file, "%d %f %f %f %f", &nsites, &xmin, &xmax, &ymin, &ymax);
/*
* read data
*/
nsites = 0;
sites = (struct Site *) myalloc (4000 * sizeof (struct Site));
while (fscanf (file, "%f %f", &sites[nsites].coord.x, &sites[nsites].coord.y) != EOF) {
sites[nsites].sitenbr = nsites;
sites[nsites].refcnt = 0;
nsites += 1;
if (nsites % 4000 == 0)
sites = (struct Site *) realloc (sites, (nsites + 4000) * sizeof (struct Site));
}
/*
* sort data and find extrema
*/
qsort (sites, nsites, sizeof (struct Site), scomp);
xmin = sites[0].coord.x;
xmax = sites[0].coord.x;
for (i = 1; i < nsites; i += 1) {
if (sites[i].coord.x < xmin)
xmin = sites[i].coord.x;
if (sites[i].coord.x > xmax)
xmax = sites[i].coord.x;
}
ymin = sites[0].coord.y;
ymax = sites[nsites - 1].coord.y;
#ifdef SHOW_DATA
printf ("\n...data after sorting:\n");
printf ("...parameters: nsites: %4d", nsites);
printf ("\n extrema: %f %f %f %f\n", xmin, xmax, ymin, ymax);
for (i = 0; i < nsites; i += 1) {
printf (" x[%d] = %f y[%d] = %f\n",
i, (sites + i)->coord.x, i, (sites + i)->coord.y);
}
#endif
}
/*
* readone()
* DESCRIPTION:
* read one site
* ARGUMENTS:
* none
* RETURN VALUE:
* site (struct Site *)
*/
struct Site *
readone ()
{
struct Site *s;
s = (struct Site *) getfree (&sfl);
s->refcnt = 0;
s->sitenbr = siteidx;
siteidx += 1;
if (fscanf (fpIn, "%f %f", &(s->coord.x), &(s->coord.y)) == EOF)
return ((struct Site *) NULL);
#ifdef SHOW_DATA
printf ("\n...READONE: fetching site: x[%d] = %f y[%d] = %f\n",
siteidx, s->coord.x, siteidx, s->coord.y);
#endif
return (s);
}
void
exit_messg (str, code)
char *str;
int code;
{
printf ("\n%s", str);
exit (code);
}
/*
* usage of routine
*/
void
usage (char *progname)
{
progname = last_bs (progname);
printf ("USAGE: %s infile outimg [-w file] [-s] [-t] [-g] [-L]\n", progname);
printf ("\n%s constructs Voronoi diagram or Delaunay triangulation\n", progname);
printf ("for a set of points in the plane using Fortune's algorithm.\n");
printf ("[Fortune 1984]\n\n");
printf ("ARGUMENTS:\n");
printf (" infile: input filename (.vin) (ASCII)\n");
printf (" produced by spp or xah; assumes y-sorted\n");
printf (" site coordinates unless option -s invoked.\n");
printf (" outimg: output image filename (TIF)\n\n");
printf ("OPTIONS:\n");
printf (" -w file : write output to file ( .vdt) as well as stdout\n");
printf (" -s: y-sort data in input file\n");
printf (" -t: perform Delaunay triangulation\n");
printf (" -g: debug mode\n");
printf (" -L: print Software License for this module\n");
exit (1);
}
void
main (int argc, char *argv[])
{
struct Site *(*next) (); /* next is declared to be a ptr */
/* to a function which returns a
* /* ptr to struct Site */
int ic, is;
int i_arg;
char *buf;
Image *imgOut;
static char wbuf[20];
static char *inp_suffix =
{".xxx"}; /* default inp file suffix */
static char *vin_type =
{".vin"}; /* suffix for .vin inp file */
static char *vsuffix =
{".vdt"}; /* suffix for V. outp file name */
static char *dsuffix =
{".ddt"}; /* suffix for D. outp file name */
int reset = 1, no_reset = 0;
/*
* cmd line options
*/
static char *optstring = "w:stgL";
buf = argv[1];
/*
* parse command line
*/
optind = 3;
opterr = ON; /* give error messages */
if (argc < 3)
usage (argv[0]);
while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
switch (i_arg) {
case 'w':
printf ("...option %c: ", i_arg);
strcpy (wbuf, optarg);
if ((fpOut = fopen (wbuf, "w")) == NULL) {
printf ("\n...cannot open %s for writing\n",
wbuf);
exit (1);
}
printf ("write data to file %s\n", wbuf);
WRITE_FLAG = ON;
break;
case 's':
printf ("...option %c: ", i_arg);
printf ("perform sort on y-coord. of input\n");
PRE_SORTED = OFF;
break;
case 't':
printf ("...option %c: perform Delaunay triangulation\n", i_arg);
VOR = OFF;
TRIANGULATE = ON;
/* construct new output file name */
ic = 0;
while ((*(wbuf + ic) = *(buf + ic)) != '.')
ic++;
for (is = 0; is < 4; is++)
*(wbuf + (ic) + is) = *(dsuffix + is);
break;
case 'g':
printf ("...option %c: debug mode\n", i_arg);
DBG = ON;
break;
case 'L':
print_sos_lic ();
exit (0);
default:
printf ("...unknown condition encountered\n");
exit (1);
break;
}
}
printf ("read data from file %s\n", buf);
/* get size of data set from file */
if ((fpIn = fopen (buf, "r")) == NULL) {
printf ("\n...cannot open input file %s\n", buf);
exit (1);
}
/* construct output file name */
ic = 0;
while ((*(wbuf + ic) = *(buf + ic)) != '.')
ic++;
for (is = 0; is < 4; is++)
*(wbuf + (ic) + is) = *(vsuffix + is);
/* strip input file suffix */
for (is = 0; is < 4; is++)
*(inp_suffix + is) = *(buf + ic + is);
#ifdef PORTING
printf ("\n...give size of all structures defined in header file:\n");
printf (" struct Freenode: %d\n", sizeof (struct Freenode));
printf (" struct Freelist: %d\n", sizeof (struct Freelist));
printf (" struct Point: %d\n", sizeof (struct Point));
printf (" struct Site: %d\n", sizeof (struct Site));
printf (" struct Edge: %d\n", sizeof (struct Edge));
printf (" struct Halfedge: %d\n", sizeof (struct Halfedge));
#endif
/*
* get data from input file
*/
if (strcmp (inp_suffix, vin_type) == 0) {
freeinit (&sfl, sizeof (struct Site));
if (PRE_SORTED == ON) {
fscanf (fpIn, "%d %f %f %f %f",
&nsites, &xmin, &xmax, &ymin, &ymax);
next = readone;
}
else {
freadsites (fpIn);
next = nextone;
}
printf ("\n...initialize geometry settings...\n");
siteidx = 0;
geominit ();
/* allocate default image buffer for image output */
imgOut = ImageAlloc ((long) (ymin + ymax), (long) (xmin + xmax), BPS);
printf ("\n...initialize plotting...\n");
plotinit (imgOut);
if (VOR == ON)
printf ("\n...start voronoi construction...\n");
else if (TRIANGULATE == ON)
printf ("\n...start Delaunay triangulation...\n");
voronoi (next, imgOut, WHITE);
}
else
exit_messg ("\n...unknown inp file suffix", 1);
if (WRITE_FLAG == ON)
fclose (fpOut);
printf ("\n...writing graphics output file %s\n", argv[2]);
ImageOut (argv[2], imgOut);
fclose (fpIn);
}